package com.xhwl.logistics.service.cent.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.vehicle.feign.VehicleIOCCommonQuery;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.visitor.VisitorInfo;
import com.xhwl.common.query.cent.device.DevicePageQuery;
import com.xhwl.common.query.cent.visitor.VisitorInfoQuery;
import com.xhwl.logistics.bo.cent.VehicleIntegratedConfigBO;
import com.xhwl.logistics.dao.mapper.IVehicleAccessRecordMapper;
import com.xhwl.logistics.dao.mapper.IVehicleCarMapper;
import com.xhwl.logistics.dto.VehicleIOCStatisticsDTO;
import com.xhwl.logistics.dto.http.*;
import com.xhwl.logistics.entity.VehicleAccessRecord;
import com.xhwl.logistics.entity.VehicleArea;
import com.xhwl.logistics.entity.VehicleCar;
import com.xhwl.logistics.entity.VehiclePassage;
import com.xhwl.logistics.enums.VehicleCarTypeEnum;
import com.xhwl.logistics.service.cent.IDeviceService;
import com.xhwl.logistics.service.cent.IVisitorInfoCentService;
import com.xhwl.logistics.service.cent.QueryDeviceService;
import com.xhwl.logistics.service.impl.VehicleAreaServiceImpl;
import com.xhwl.logistics.service.impl.VehiclePassageServiceImpl;
import com.xhwl.logistics.service.impl.http.DaHuaHttpServiceImpl;
import com.xhwl.logistics.service.impl.http.HongMenHttpServiceImpl;
import com.xhwl.logistics.util.MathUtil;
import com.xhwl.logistics.vo.unique.VehicleMNPassageRecordVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: wuyuhao
 * @createDate: 2023/3/9 13:33
 */
//@Service
public class VehicleIOCServiceImpl implements IVehicleIOCService {

    @Resource
    private QueryDeviceService queryDeviceService;

    @Resource
    private DaHuaHttpServiceImpl daHuaHttpService;

    @Resource
    private HongMenHttpServiceImpl hongMenHttpService;

    @Resource
    private VehicleAreaServiceImpl vehicleAreaService;

    @Resource
    private IVehicleAccessRecordMapper vehicleAccessRecordMapper;

    @Resource
    private IVehicleCarMapper vehicleCarMapper;

    @Resource
    private IVisitorInfoCentService visitorInfoCentService;

    @Autowired
    private VehiclePassageServiceImpl vehiclePassageService;

    @Autowired
    private IDeviceService deviceService;

    @Override
    public ResultJson carPotStatistics(Integer projectId, Integer type) {
        if (ObjectUtils.isEmpty(projectId)) {
            throw new BusinessException("项目id不能为空");
        }
        if (ObjectUtils.isEmpty(type)) {
            throw new BusinessException("type不能为空");
        }
        VehicleIntegratedConfigBO vehicleIntegratedConfigBO = queryDeviceService.queryIntegratedConfigFromProjectId(projectId);
        Integer total = 0;
        Integer empty = 0;
        Integer used = 0;
        if (type == 1) {
            //根据集成配置中的remark字段获取大华车场车位信息，并将其封装到ParkingLotIOCDTO类中
            List<VehicleArea> vehicleAreaList = vehicleAreaService.list(new LambdaQueryWrapper<VehicleArea>()
                    .eq(VehicleArea::getRemark, vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemark()));
            if (vehicleAreaList.size() > 1) {
                throw new BusinessException("通过该区域备注找到多个区域信息！");
            } else if (vehicleAreaList.size() == 0) {
                throw new BusinessException("通过该区域备注未找到区域信息！");
            }
            VehicleArea vehicleArea = vehicleAreaList.get(0);
            List<ParkingLotAreaInfoDaHuaDTO> parkingLotAreaInfo = daHuaHttpService.getParkingLotAreaInfo(vehicleIntegratedConfigBO);
            if (!CollectionUtils.isEmpty(parkingLotAreaInfo)) {
                ParkingLotAreaInfoDaHuaDTO parkingLotAreaInfoDaHuaDTO = parkingLotAreaInfo.stream()
                        .filter(s -> StringUtils.equals(s.getId(), vehicleArea.getThirdAreaId()))
                        .findAny()
                        .orElse(null);
                if (parkingLotAreaInfoDaHuaDTO == null) {
                    throw new BusinessException("大华将该区域删除，请同步最新区域！");
                }
                total = parkingLotAreaInfoDaHuaDTO.getTotalLot();
                empty = parkingLotAreaInfoDaHuaDTO.getIdleLot();
                used = parkingLotAreaInfoDaHuaDTO.getUsedLot();
            }
        } else if (type == 2) {
            String customParams = vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getCustomParams();
            JSONObject customParamsObj = JSON.parseObject(customParams);
            if (customParamsObj.getBoolean("doubleFunContrMn")) {
                String host = customParamsObj.getString("host");
                JSONObject object = hongMenHttpService.queryParkingLot(host);
                Integer parkingTotal = object.getInteger("parking_total");
                Integer parkingTotalRemain = object.getInteger("parking_total_remain");
                total += parkingTotal;
                empty += parkingTotalRemain;
                used += (parkingTotal - parkingTotalRemain);
            } else {
                return ResultJson.fail("未开启双厂商配置");
            }
        } else {
            return ResultJson.fail("不支持的type类型");
        }
        ParkingLotIOCDTO parkingLotIOCDTO = new ParkingLotIOCDTO();
        parkingLotIOCDTO.setTotal(total);
        parkingLotIOCDTO.setEmpty(empty);
        parkingLotIOCDTO.setUsed(used);
        // 根据车位信息求出车位的空置率和使用率
        parkingLotIOCDTO.setEmptyRate(MathUtil.getRateFromInterger(total, empty, true));
        parkingLotIOCDTO.setUsedRate(MathUtil.getRateFromInterger(total, used, true));
        return ResultJson.successWithResult(parkingLotIOCDTO);
    }

    @Override
    public ResultJson carTypeNumStatistics(Integer projectId, Integer type) {
        if (ObjectUtils.isEmpty(projectId)) {
            throw new BusinessException("项目id不能为空");
        }
        if (ObjectUtils.isEmpty(type)) {
            throw new BusinessException("type不能为空");
        }
        // 获取最新的车进入记录
        List<VehicleAccessRecord> accessRecords = vehicleAccessRecordMapper.listAccessRecordByPrjAndThirdParkId(projectId, "02");
        List<String> plateNumbers;
        if (type == 1) {
            // 过滤出大华生活区的车牌
            plateNumbers = accessRecords.stream()
                    .filter(e -> e.getEnterPassageName() != null && e.getEnterPassageName().contains("宿舍"))
                    .map(VehicleAccessRecord::getPlateNumber)
                    .collect(Collectors.toList());
        } else if (type == 2) {
            // 过滤出红门办公区的车牌
            plateNumbers = accessRecords.stream()
                    .filter(e -> e.getEnterPassageName() != null && e.getEnterPassageName().contains("东门"))
                    .map(VehicleAccessRecord::getPlateNumber)
                    .collect(Collectors.toList());
        } else {
            return ResultJson.fail("不支持的type类型");
        }
        // 获取车列表
        List<CarTypeNumIOCDTO> carTypeNumIOCDTOS = vehicleCarMapper.countNumberByCarType(projectId, plateNumbers);
        // 获取车总数
        Integer total = vehicleCarMapper.selectCount(new LambdaQueryWrapper<VehicleCar>()
                .eq(VehicleCar::getDeleted, 0)
                .eq(VehicleCar::getProjectId, projectId));
        carTypeNumIOCDTOS.forEach(e -> {
            Integer carType = e.getCarType();
            e.setCarTypeName(VehicleCarTypeEnum.toVehicleCarTypeEnum(carType).getDescription());
            String usedRate = MathUtil.getRateFromInterger(total, e.getUsed(), true);
            e.setUsedRate(usedRate);
        });
        return ResultJson.successWithResult(carTypeNumIOCDTOS);
    }

    @Override
    public ResultJson pageCarRecord(VehicleIOCCommonQuery commonQuery) {
        Integer projectId = commonQuery.getProjectId();
        if (ObjectUtils.isEmpty(projectId)) {
            throw new BusinessException("项目id不能为空");
        }
        Integer page = commonQuery.getPage();
        if (ObjectUtils.isEmpty(page)) {
            page = 1;
        }
        Integer size = commonQuery.getSize();
        if (ObjectUtils.isEmpty(size)) {
            size = -1;
        }
        Page<VehicleAccessRecord> recordPage = vehicleAccessRecordMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper<VehicleAccessRecord>()
                .eq(VehicleAccessRecord::getProjectId, projectId)
                .orderByDesc(VehicleAccessRecord::getCreatedAt));
        List<VehicleCar> vehicleCars = vehicleCarMapper.selectList(new LambdaQueryWrapper<VehicleCar>()
                .eq(VehicleCar::getProjectId, projectId)
                .eq(VehicleCar::getDeleted, 0));
        List<String> plateNumbers = new ArrayList<>();
        if (!CollectionUtils.isEmpty(vehicleCars)) {
            plateNumbers = vehicleCars.stream().map(VehicleCar::getPlateNumber).collect(Collectors.toList());
        }
        List<String> finalPlateNumbers = plateNumbers;
        List<VehicleAccessRecord> records = recordPage.getRecords();
        List<CarRecordIOCDTO> carRecordIOCDTOS = records.stream().map(e -> {
            CarRecordIOCDTO carRecordIOCDTO = new CarRecordIOCDTO();
            carRecordIOCDTO.setId(e.getId());
            carRecordIOCDTO.setStatus(e.getStatus());
            carRecordIOCDTO.setPlateNumber(e.getPlateNumber());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (!ObjectUtils.isEmpty(e.getEnterPassageName())) {
                carRecordIOCDTO.setPassageName(e.getEnterPassageName());
                carRecordIOCDTO.setPassageTime(sdf.format(e.getEnterTime()));
                carRecordIOCDTO.setPassagePic(e.getEnterPictureUrl());
            }
            if (!ObjectUtils.isEmpty(e.getExitPassageName())) {
                carRecordIOCDTO.setPassageName(e.getExitPassageName());
                carRecordIOCDTO.setPassageTime(sdf.format(e.getExitTime()));
                carRecordIOCDTO.setPassagePic(e.getExitPictureUrl());
            }
            // 判断车类型：内部车、临时车
            if (finalPlateNumbers.contains(e.getPlateNumber())) {
                carRecordIOCDTO.setVehicleType("内部车");
            } else {
                carRecordIOCDTO.setVehicleType("临时车");
            }
            return carRecordIOCDTO;
        }).collect(Collectors.toList());
        Page<CarRecordIOCDTO> carRecordIOCDTOPage = new Page<>();
        BeanUtils.copyProperties(recordPage, carRecordIOCDTOPage);
        carRecordIOCDTOPage.setRecords(carRecordIOCDTOS);
        return ResultJson.successWithResult(carRecordIOCDTOPage);
    }

    public ResultJson statisticsVehicleInPark(VehicleIOCCommonQuery commonQuery) {
        Integer projectId = commonQuery.getProjectId();
        if (ObjectUtils.isEmpty(projectId)) {
            throw new BusinessException("项目id不能为空");
        }
        Integer total = 0;
        Integer empty = 0;
        Integer used = 0;
        // 大华车位信息获取
        VehicleIntegratedConfigBO vehicleIntegratedConfigBO = queryDeviceService.queryIntegratedConfigFromProjectId(projectId);
        List<ParkingLotAreaInfoDaHuaDTO> parkingLotAreaInfo = daHuaHttpService.getParkingLotAreaInfo(vehicleIntegratedConfigBO);
        if (!CollectionUtils.isEmpty(parkingLotAreaInfo)) {
            for (ParkingLotAreaInfoDaHuaDTO dto : parkingLotAreaInfo) {
                total += dto.getTotalLot();
                empty += dto.getIdleLot();
                used += dto.getUsedLot();
            }
        }
        // 红门车位信息获取
        String customParams = vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getCustomParams();
        JSONObject customParamsObj = JSON.parseObject(customParams);
        if (customParamsObj.getBoolean("doubleFunContrMn")) {
            String host = customParamsObj.getString("host");
            JSONObject object = hongMenHttpService.queryParkingLot(host);
            Integer parkingTotal = object.getInteger("parking_total");
            Integer parkingTotalRemain = object.getInteger("parking_total_remain");
            total += parkingTotal;
            empty += parkingTotalRemain;
            used += (parkingTotal - parkingTotalRemain);
        }
        ParkingLotIOCDTO parkingLotIOCDTO = new ParkingLotIOCDTO();
        parkingLotIOCDTO.setTotal(total);
        parkingLotIOCDTO.setEmpty(empty);
        parkingLotIOCDTO.setUsed(used);
        // 根据车位信息求出车位的空置率和使用率
        parkingLotIOCDTO.setEmptyRate(MathUtil.getRateFromInterger(total, empty, true));
        parkingLotIOCDTO.setUsedRate(MathUtil.getRateFromInterger(total, used, true));
        // 今日出入车辆数统计
        Integer enterCount = vehicleAccessRecordMapper.countAccessRecordsToday(projectId, 0);
        Integer leaveCount = vehicleAccessRecordMapper.countAccessRecordsToday(projectId, 1);
        parkingLotIOCDTO.setEnterNumToday(enterCount);
        parkingLotIOCDTO.setLeaveNumToday(leaveCount);
        return ResultJson.successWithResult(parkingLotIOCDTO);
    }

    @Override
    public ResultJson carClassifyNumStatistics(VehicleIOCCommonQuery commonQuery) {
        Integer projectId = commonQuery.getProjectId();
        /*
         * 1.查询员工车：在vehicle_car中出现的车是员工车
         * 2.查询物流车：在vehc_car_record中南门的车，且不在vehicle_car中的车是物流车
         * 3.查询访客车：在vehc_car_record中的车，且在visitor_info中的车是访客车
         * */
        List<CarClassifyNumIOCDTO> list = new ArrayList<>();
        // 员工车
        List<VehicleCar> vehicleCars = vehicleCarMapper.selectList(new LambdaQueryWrapper<VehicleCar>()
                .eq(VehicleCar::getDeleted, 0)
                .eq(VehicleCar::getProjectId, projectId));
        int staffCarCount = ObjectUtils.isEmpty(vehicleCars) ? 0 : vehicleCars.size();
        List<String> plateNumbers = vehicleCars.stream()
                .map(VehicleCar::getPlateNumber)
                .collect(Collectors.toList());
        // 物流车
        Integer logisticsCarCount = vehicleAccessRecordMapper.selectCount(new LambdaQueryWrapper<VehicleAccessRecord>()
                .eq(VehicleAccessRecord::getProjectId, projectId)
                .notIn(VehicleAccessRecord::getPlateNumber, plateNumbers)
                .and(e -> e.like(VehicleAccessRecord::getEnterPassageName, "南门")
                        .or()
                        .like(VehicleAccessRecord::getExitPassageName, "南门")
                ));
        // 访客车
        VisitorInfoQuery query = new VisitorInfoQuery();
        query.setProjectId(projectId);
        List<VisitorInfo> visitorInfos = visitorInfoCentService.listVisitorInfoWithCar(query);
        List<String> carNums = visitorInfos.stream()
                .map(VisitorInfo::getCarNum)
                .collect(Collectors.toList());
        Integer visitorCarCount = vehicleAccessRecordMapper.selectCount(new LambdaQueryWrapper<VehicleAccessRecord>()
                .eq(VehicleAccessRecord::getProjectId, projectId)
                .in(VehicleAccessRecord::getPlateNumber, carNums));
        // 统计
        int total = staffCarCount + logisticsCarCount + visitorCarCount;
        CarClassifyNumIOCDTO staffCarClassify = new CarClassifyNumIOCDTO();
        staffCarClassify.setCarTypeName("员工车");
        staffCarClassify.setUsed(staffCarCount);
        staffCarClassify.setUsedRate(MathUtil.getRateFromInterger(total, staffCarCount, true));
        list.add(staffCarClassify);
        CarClassifyNumIOCDTO logisticsCarClassify = new CarClassifyNumIOCDTO();
        logisticsCarClassify.setCarTypeName("物流车");
        logisticsCarClassify.setUsed(logisticsCarCount);
        logisticsCarClassify.setUsedRate(MathUtil.getRateFromInterger(total, logisticsCarCount, true));
        list.add(logisticsCarClassify);
        CarClassifyNumIOCDTO visitorCarClassify = new CarClassifyNumIOCDTO();
        visitorCarClassify.setCarTypeName("访客车");
        visitorCarClassify.setUsed(visitorCarCount);
        visitorCarClassify.setUsedRate(MathUtil.getRateFromInterger(total, visitorCarCount, true));
        list.add(visitorCarClassify);
        return ResultJson.success(list);
    }

    @Override
    public ResultJson accessRecordPassageStatistics(VehicleIOCStatisticsDTO commonQuery) {
        //验证请求参数的正确性
        if(commonQuery.getProjectId() == null){
            throw new BusinessException("项目id为空");
        }

        //准备请求参数，并获取出行记录的统计数据
        LinkedList<VehicleMNPassageRecordVO> vehicleMNPassageRecordVOS = new LinkedList<>();
        List<VehicleMNPassageRecordVO> vehicleAccessRecordEnters = vehicleAccessRecordMapper.listAccessRecordGroupEnter(commonQuery.getProjectId(),
                commonQuery.getStartTime(), commonQuery.getEndTime());
        List<VehicleMNPassageRecordVO> vehicleAccessRecordExists = vehicleAccessRecordMapper.listAccessRecordGroupExist(commonQuery.getProjectId(),
                commonQuery.getStartTime(), commonQuery.getEndTime());
        vehicleMNPassageRecordVOS.addAll(vehicleAccessRecordEnters);
        vehicleMNPassageRecordVOS.addAll(vehicleAccessRecordExists);
        if(vehicleMNPassageRecordVOS.isEmpty()){
            return ResultJson.success();
        }

        //获取该项目下的所有通道信息
        List<VehiclePassage> vehiclePassages = vehiclePassageService.list(new LambdaQueryWrapper<VehiclePassage>().
                eq(VehiclePassage::getProjectId, commonQuery.getProjectId()));
        if(vehiclePassages.isEmpty()){
            throw new BusinessException("该项目下没有道闸的相关信息");
        }

        //获取该项目的车行设备信息
        DevicePageQuery devicePageQuery = new DevicePageQuery();
        devicePageQuery.setProjectId(commonQuery.getProjectId());
        devicePageQuery.setCategoryId(3);
        List<DeviceDTO> deviceDTOS = deviceService.listDevice(null, devicePageQuery);

        //组装返回结果
        List<VehicleMNPassageRecordVO> vehicleMNPassageRecordVOList = vehicleMNPassageRecordVOS.stream().map(vehicleMNPassageRecordVO -> {
            //处理卡类型
            if (vehicleMNPassageRecordVO.getCardType() == null || vehicleMNPassageRecordVO.getCardType().equals(3) || vehicleMNPassageRecordVO.getCardType().equals(99)) {
                vehicleMNPassageRecordVO.setCardType(1);
            } else {
                vehicleMNPassageRecordVO.setCardType(0);
            }

            //处理通行方向和设备在离线
            if (vehicleMNPassageRecordVO.getPassageId() != null) {
                VehiclePassage vehiclePassage1 = vehiclePassages.stream().filter(vehiclePassage -> {
                    if (vehiclePassage.getId().equals(vehicleMNPassageRecordVO.getPassageId())) {
                        return true;
                    } else {
                        return false;
                    }
                }).findAny().orElse(null);
                if (vehiclePassage1 != null) {
                    vehicleMNPassageRecordVO.setPassageDir(vehiclePassage1.getType());
                    String[] deviceStrArr = vehiclePassage1.getRemark().split(",");
                    List<String> thirdDeviceIds = Arrays.stream(deviceStrArr).collect(Collectors.toList());
                    if (!deviceDTOS.isEmpty()) {
                        List<DeviceDTO> deviceDTOList = deviceDTOS.stream().filter(deviceDTO -> {
                            if (thirdDeviceIds.contains(deviceDTO.getThirdDeviceId())) {
                                return true;
                            } else {
                                return false;
                            }
                        }).collect(Collectors.toList());
                        if (!deviceDTOList.isEmpty()) {
                            vehicleMNPassageRecordVO.setDeviceStatus(deviceDTOList.get(0).getOnlineStatus());
                            vehicleMNPassageRecordVO.setDeviceId(deviceDTOList.get(0).getId());
                        }
                    }
                }
            }

            return vehicleMNPassageRecordVO;
        }).collect(Collectors.toList());

        return ResultJson.success(vehicleMNPassageRecordVOList);
    }
}
